namespace ScrumSprintMonitor.Implementation.Configuration
{
	#region #using Directives

	using System;
	using System.Globalization;
	using System.IO;
	using System.Xml;

	using Infrastructure;

	#endregion

	public class WritableXmlStreamBasedTeamInfoProvider : XmlStreamBasedTeamInfoProvider
	{
		public WritableXmlStreamBasedTeamInfoProvider(IDataStreamProvider xmlStreamProvider, ILogger<XmlStreamBasedTeamInfoProvider> logger)
			: base(null, xmlStreamProvider, null, logger)
		{
			this.initialized = true;
		}

		public override bool IsReadOnly
		{
			get
			{
				GuardDisposed();

				return this.streamProvider.IsReadOnly;
			}
		}

		public void AddTeamMember(ITeamMemberInformation teamMemberInfo)
		{
			if (string.IsNullOrEmpty(teamMemberInfo.Name))
			{
				this.unassignedTeamMemberInfo = teamMemberInfo;
				return;
			}

			this.dictionary.Add(teamMemberInfo.Name, teamMemberInfo);
		}

		public override void Save()
		{
			GuardDisposed();

			try
			{
				FreezeStreamChangeNotifications();

				using (var stream = this.streamProvider.OpenStream(FileAccess.Write))
				{
					var settings = new XmlWriterSettings {
					                                     	Indent = true,
															NewLineOnAttributes = true
					                                     };

					using (var writer = XmlWriter.Create(stream, settings))
					{
						if (writer != null)
						{
							writer.WriteStartElement("team-members");

							if (this.unassignedTeamMemberInfo != null)
							{
								WriteTeamMemberInfo(writer, this.unassignedTeamMemberInfo);
							}
							foreach (var teamMember in TeamMembers)
							{
								WriteTeamMemberInfo(writer, teamMember);
							}

							writer.WriteEndElement();
						}
					}
				}
			}
			finally
			{
				UnfreezeStreamChangeNotifications();
			}
		}

		private static void WriteTeamMemberInfo(XmlWriter writer, ITeamMemberInformation teamMember)
		{
			writer.WriteStartElement("team-member");

			writer.WriteAttributeString("name", teamMember.Name);
			if (string.IsNullOrEmpty(teamMember.Name))
			{
				writer.WriteAttributeString("unassigned", true.ToString(CultureInfo.InvariantCulture));
			}
			if (teamMember.DisplayAlias != teamMember.Name)
			{
				writer.WriteElementString("display-alias", teamMember.DisplayAlias);
			}
			if (teamMember.SchedulerAlias != teamMember.Name)
			{
				writer.WriteElementString("scheduler-alias", teamMember.SchedulerAlias);
			}
			writer.WriteElementString("team", teamMember.Team);
			writer.WriteElementString("time-zone", teamMember.TimeZone.Id);
			writer.WriteElementString("dedicated-to-sprint", teamMember.DedicatedToSprint.ToString(CultureInfo.InvariantCulture));
			writer.WriteElementString("hourly-productivity-factor", teamMember.HourlyProductivityFactor.ToString(CultureInfo.InvariantCulture));
			writer.WriteStartElement("workday");
			writer.WriteElementString("start", teamMember.GetWorkdayStart(SystemTime.Now()).TimeOfDay.ToString());
			writer.WriteElementString("end", teamMember.GetWorkdayEnd(SystemTime.Now()).TimeOfDay.ToString());
			writer.WriteEndElement();
			writer.WriteStartElement("lunch");
			writer.WriteElementString("start", TimeSpan.FromHours(12).ToString());
			writer.WriteElementString("end", TimeSpan.FromHours(13).ToString());
			writer.WriteEndElement();
			writer.WriteEndElement();
		}
	}
}